package com.jaret.demo.redis;

import com.google.common.collect.Maps;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author jaret
 * @date 2024/5/11 11:29
 * @description
 */
@Component
public class RedisDemo {


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    public void testOther() {
        Set<String> keys = redisTemplate.keys("test*");
        System.out.println(keys);
    }

    public void testRedisson() {
        RLock lock = null;
        try {
            lock = redissonClient.getLock("anyLock");
            //尝试获取锁，参数分别是：获取锁的最大等待时间(期间会重试)，锁自动释放时间，时间单位
            boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
            if (isLock) {
                try {
                    System.out.println("执行业务");
                } finally {
                    if (lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            }
        } catch (Exception e) {
            // 记录异常
            e.printStackTrace();
        } finally {
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public void testStream() {
        StreamOperations<String, Object, Object> opsForStream = redisTemplate.opsForStream();
        HashMap<Object, Object> map = Maps.newHashMap();
        map.put("name", "jaret");
        map.put("age", 26);
        opsForStream.add("channel1", map);

        HashMap<Object, Object> map2 = Maps.newHashMap();
        map2.put("name", "wcj");
        map2.put("age", 18);
        opsForStream.add("channel2", map2);
    }

    public void testBitMap() {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        Integer userId = 1234;
        Boolean testBitmap = opsForValue.setBit("testBitmap", userId, true);
        boolean isonline = opsForValue.getBit("testBitmap", userId).booleanValue();
        System.out.println(isonline);
    }

    public void testBloomFilter() {
        // 创建一个预计元素数量为 1000，误报率为 0.001 的布隆过滤器
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), 1000, 0.001);

        // 向布隆过滤器中添加元素
        bloomFilter.put("hello");
        bloomFilter.put("world");

        // 检查元素是否可能存在于布隆过滤器中
        boolean mightContainHello = bloomFilter.mightContain("hello");
        boolean mightContainWorld = bloomFilter.mightContain("world");
        boolean mightContainNotExist = bloomFilter.mightContain("notExist");

        System.out.println("可能存在于布隆过滤器中的元素: ");
        System.out.println(Arrays.toString(new boolean[]{mightContainHello, mightContainWorld, mightContainNotExist}));
    }


    public void testGeo() {
        GeoOperations<String, Object> opsForGeo = redisTemplate.opsForGeo();
        HashMap<Object, Point> map = new HashMap<>();
        map.put("小明餐厅", new Point(116.40, 39.90));
        map.put("小芳餐厅", new Point(121.48, 31.22));
        map.put("小军餐厅", new Point(113.33, 23.13));
        map.put("小丽餐厅", new Point(104.06, 30.57));
        Long testGeo = opsForGeo.add("test_geo", map);
        System.out.println("添加了：" + testGeo);
        List<Point> position = opsForGeo.position("test_geo", "小明餐厅");
        System.out.println("获取坐标：" + position);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = opsForGeo.radius("test_geo", new Circle(new Point(116.40, 39.90), 100));
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> e : radius) {
            RedisGeoCommands.GeoLocation<Object> content = e.getContent();
            Object name = content.getName();
            Point point = content.getPoint();
            System.out.println("name: " + name + ", point: " + point);
        }

        Distance distance = opsForGeo.distance("test_geo", "小明餐厅", "小丽餐厅");
        System.out.println("distance: " + distance.getValue());
    }


    public void testHyperLogLog() {
        HyperLogLogOperations<String, Object> hyperLogLog = redisTemplate.opsForHyperLogLog();
        hyperLogLog.add("test_hyperLogLog", "a", "b", "c", "d", "e");
//        hyperLogLog.delete("test_hyperLogLog");
        Long testHyperLogLog = hyperLogLog.size("test_hyperLogLog");
        System.out.println(testHyperLogLog);
    }

    public void testPipeline() {
    }


}

